package com.jerry.quartz.impl;

import com.jerry.quartz.TaskService;
import com.jerry.quartz.domain.MyJob;
import com.jerry.quartz.domain.SchedluerTask;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Shirly on 2016/12/14.
 */
@Service
public class ItaskService implements TaskService, ApplicationContextAware {


    @Autowired
    SchedulerFactoryBean schedulerFactory;


    private Map<String, SchedluerTask> allSchedTask = new LinkedHashMap<>();
    private ApplicationContext app;


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.app = applicationContext;
        String[] names = app.getBeanDefinitionNames();
        try {
            for (String name : names) {
                Class<?> clzz = app.getBean(name).getClass();
                Method[] method = clzz.getDeclaredMethods();
                for (Method m : method) {
                    if (m.isAnnotationPresent(Scheduled.class)) {
                        SchedluerTask task = createSchedluer(m);
                        addTask(task);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public Map<String, Object> getAllCron() {
        return null;
    }

    @Override
    public List<SchedluerTask> getAllTask() {
        List<SchedluerTask> alltask = new ArrayList<>();
        alltask.addAll(allSchedTask.values());
        return alltask;
    }

    @Override
    public SchedluerTask getTaskById(String taskId) {
        return null;
    }

    private SchedluerTask createSchedluer(Method m) throws Exception {
        SchedluerTask task = new SchedluerTask("" + System.currentTimeMillis());
        Class clzz = m.getDeclaringClass();
        task.setGroup(clzz.getName());
        task.setTrigger(clzz.getName() + "." + m.getName());
        if(m.isAnnotationPresent(Scheduled.class)){
            Annotation annotation = m.getAnnotation(Scheduled.class);
            Method method = annotation.getClass().getDeclaredMethod("cron");
            String cronExperess = method.invoke(annotation).toString();
            task.setCron(cronExperess);
        }
        return task;
    }

    @Override
    public SchedluerTask addTask(SchedluerTask task) throws Exception {
        Scheduler scheduler = schedulerFactory.getScheduler();

        JobDetail jobDetail = new JobDetail(task.getId(), task.getGroup(), MyJob.class);
        CronTrigger cronTrigger = new CronTrigger(task.getId(), task.getTrigger());
        cronTrigger.setCronExpression(task.getCron());
        Class clzz = Class.forName(task.getGroup());

        //无缝集成
        Object obj = null;
        try {
            if (null == app.getBean(clzz)) {
                obj = clzz.newInstance();
            } else {
                obj = app.getBean(clzz);
            }
        } catch (Exception e) {
            obj = clzz.newInstance();
        }

        cronTrigger.getJobDataMap().put(MyJob.DATA_TARGET_KEY, obj);
        Method method = clzz.getMethod(task.getTrigger().replaceAll(task.getGroup() + ".", ""));
        cronTrigger.getJobDataMap().put(MyJob.DATA_TRIGGER_KEY, method);
        cronTrigger.getJobDataMap().put(MyJob.DATA_TRIGGER_PARM_KEY, new Object[]{});
        cronTrigger.getJobDataMap().put(MyJob.DATA_TASK_KEY, task);
        scheduler.scheduleJob(jobDetail, cronTrigger);

        if (!scheduler.isShutdown()) {
            scheduler.start();
        }
        if (!allSchedTask.containsKey(task.getId())) {
            allSchedTask.put(task.getId(), task);
        }

        return task;
    }

    @Override
    public SchedluerTask addTask(String taskName, String taskClassName, String triggerName, String cron) throws Exception {
        Class cl = Class.forName(taskClassName);
        Method method = cl.getDeclaredMethod(triggerName);
        SchedluerTask task = createSchedluer(method);
        task.setName(taskName);
        task.setCron(cron);
        return addTask(task);
    }

    @Override
    public SchedluerTask addtask(String taskName, String taskClassName, String taskGroupName, String triggerName, String triggerGroupName, String cron) {
        return null;
    }

    @Override
    public SchedluerTask modifyTask(String taskId, String cron) {
        return null;
    }

    @Override
    public SchedluerTask removeTask(String taskId) {
        SchedluerTask task = allSchedTask.get(taskId);
        Scheduler scheduler = schedulerFactory.getScheduler();
        try {
            scheduler.pauseTrigger(taskId,task.getTrigger());
            scheduler.unscheduleJob(taskId,task.getGroup());
            scheduler.deleteJob(taskId,task.getGroup());
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return task;
    }

    @Override
    public SchedluerTask pauseTask(String taskId) {
        SchedluerTask task = allSchedTask.get(taskId);
        Scheduler scheduler = schedulerFactory.getScheduler();
        try {
            if(!scheduler.isInStandbyMode()){
                scheduler.standby();
            }
            for (int i = 0; i <10 ; i++) {
                System.out.println("任务暂停了："+(i+1)+"%");
            }
            scheduler.start();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return task;
    }

    @Override
    public SchedluerTask disableTask(String taskId) {
        return null;
    }

    @Override
    public void startAllTask() {

    }

    @Override
    public void shutdownAllTask() {

    }

}
